import os
from typing import List, Dict, Callable, Optional
from pathlib import Path
import logging
import asyncio

logger = logging.getLogger(__name__)

class FileScanner:
    @staticmethod
    async def scan_directory(directory: str, progress_callback: Optional[Callable[[int, int, str], None]] = None) -> List[Dict]:
        """扫描指定目录，返回所有文件信息"""
        files = []
        total_files = 0
        processed_files = 0
        
        try:
            # 首先计算总文件数
            for root, _, filenames in os.walk(directory):
                total_files += len(filenames)
            
            if progress_callback:
                progress_callback(0, total_files, f"开始扫描目录: {directory}")
            
            # 扫描文件
            for root, _, filenames in os.walk(directory):
                for filename in filenames:
                    file_path = os.path.join(root, filename)
                    try:
                        files.append({
                            "name": filename,
                            "path": file_path,
                            "size": os.path.getsize(file_path)
                        })
                        processed_files += 1
                        
                        # 每处理100个文件或每秒更新一次进度
                        if processed_files % 100 == 0 or processed_files == total_files:
                            if progress_callback:
                                progress_callback(processed_files, total_files, f"已扫描 {processed_files}/{total_files} 个文件")
                            # 让出控制权，避免阻塞
                            await asyncio.sleep(0.001)
                            
                    except OSError as e:
                        logger.error(f"读取文件 {file_path} 失败: {str(e)}")
                        processed_files += 1
                        
        except Exception as e:
            logger.error(f"扫描目录 {directory} 失败: {str(e)}")
            
        return files

    @staticmethod
    async def compare_files(local_files: List[Dict], seeding_files: List[str], progress_callback: Optional[Callable[[int, int, str], None]] = None) -> List[Dict]:
        """比较本地文件和做种文件，返回未做种的文件列表"""
        not_seeding = []
        seeding_paths = [os.path.normpath(path) for path in seeding_files]
        total_files = len(local_files)
        processed_files = 0
        
        if progress_callback:
            progress_callback(0, total_files, "开始比较文件...")
        
        for file in local_files:
            file_path = os.path.normpath(file["path"])
            if file_path not in seeding_paths:
                logger.info(f"未做种文件: {file_path}")
                not_seeding.append({
                    "name": file["name"],
                    "path": file["path"],
                    "size": file["size"],
                    "status": "not_seeding"
                })
            
            processed_files += 1
            
            # 每处理1000个文件更新一次进度
            if processed_files % 1000 == 0 or processed_files == total_files:
                if progress_callback:
                    progress_callback(processed_files, total_files, f"已比较 {processed_files}/{total_files} 个文件")
                # 让出控制权
                await asyncio.sleep(0.001)
        
        return not_seeding
